package com.lingjtx.common.pay.client;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lingjtx.common.core.handle.ObjectPool;
import com.lingjtx.common.core.util.StringUtil;
import com.lingjtx.common.other.http.Call;
import com.lingjtx.common.other.http.Network;
import com.lingjtx.common.pay.common.PayUrlPath;
import com.lingjtx.common.pay.config.WePayConfigProperties;
import com.lingjtx.common.pay.model.OrderEntity;
import com.lingjtx.common.pay.model.wx.*;
import com.lingjtx.common.pay.util.WePaySignatureUtil;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.net.http.HttpClient;

@Component
public class PaymentExecutor {

    private final ObjectPool<HttpClient> httpObjectPoolTemplate;
    private final WePayConfigProperties properties;

    public PaymentExecutor(@Qualifier("httpObjectPoolTemplate") ObjectPool<HttpClient> httpObjectPoolTemplate,
                           WePayConfigProperties properties) {
        this.httpObjectPoolTemplate = httpObjectPoolTemplate;
        this.properties = properties;
    }

    public WePayConfigProperties getProperties() {
        return properties;
    }

    public Certificates getCertificates() {
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);

        String token = WePaySignatureUtil.getToken("GET", PayUrlPath.WX_CERTIFICATES, "", properties);
        Call<Certificates> call = service.getCertificates(token);
        return call.execute();
    }

    public WinXinPrepayResponse wxPayNative(OrderEntity model) {
        WinXinPrepayRequest request = new WinXinPrepayRequest(model.getDesc(),
                model.getOrderNo(), properties.getNotifyUrl(), model.getPrice());
        request.setAppid(properties.getGzhAppid());
        request.setMchid(properties.getMchid());

        String token = WePaySignatureUtil.getToken("POST", PayUrlPath.WX_NATIVE_ORDER,
                JSON.toJSONString(request), properties);
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);
        Call<WinXinPrepayResponse> call = service.wxPayNative(token, request);
        return call.execute();
    }

    public WinXinPrepayResponse wxPayJsapi(OrderEntity model) {
        WinXinPrepayRequest request = new WinXinPrepayRequest(model.getDesc(),
                model.getOrderNo(), properties.getNotifyUrl(), model.getPrice());
        request.setAppid(properties.getMiniAppid());
        request.setMchid(properties.getMchid());
        PayerEntity payer = new PayerEntity(model.getOpenid());
        request.setPayer(payer);

        String token = WePaySignatureUtil.getToken("POST", PayUrlPath.WX_JSAPI_ORDER,
                JSON.toJSONString(request), properties);
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);
        Call<WinXinPrepayResponse> call = service.wxPayJsapi(token, request);
        return call.execute();
    }

    public WinXinPrepayResponse wxPayApp(OrderEntity model) {
        WinXinPrepayRequest request = new WinXinPrepayRequest(model.getDesc(),
                model.getOrderNo(), properties.getNotifyUrl(), model.getPrice());
        request.setAppid(properties.getAppid());
        request.setMchid(properties.getMchid());

        String token = WePaySignatureUtil.getToken("POST", PayUrlPath.WX_APP_ORDER,
                JSON.toJSONString(request), properties);
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);
        Call<WinXinPrepayResponse> call = service.wxPayApp(token, request);
        return call.execute();
    }


    public WinXinPrepayResponse wxPayH5(OrderEntity model) {
        WinXinPrepayRequest request = new WinXinPrepayRequest(model.getDesc(),
                model.getOrderNo(), properties.getNotifyUrl(), model.getPrice());
        request.setAppid(properties.getGzhAppid());
        request.setMchid(properties.getMchid());
        SceneInfo sceneInfo = new SceneInfo(model.getClientIp(), model.getH5Type());
        request.setScene_info(sceneInfo);

        String token = WePaySignatureUtil.getToken("POST", PayUrlPath.WX_H5_ORDER,
                JSON.toJSONString(request), properties);
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);
        Call<WinXinPrepayResponse> call = service.wxPayH5(token, request);
        return call.execute();
    }

    public WinXinOrderDetail wxQueryOrderDetail(String orderNo) {
        String mchid = properties.getMchid();
        String path = PayUrlPath.WX_QUERY_ORDER.replace("{out_trade_no}", orderNo) + "?mchid=" + mchid;
        String token = WePaySignatureUtil.getToken("GET", path, "", properties);
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);
        Call<WinXinOrderDetail> call = service.wxQueryOrderDetail(token, mchid, orderNo);
        return call.execute();
    }

    public JSONObject wxCloseOrder(String orderNo) {
        MchEntity mchid = new MchEntity(properties.getMchid());
        String path = PayUrlPath.WX_CLOSE_ORDER.replace("{out_trade_no}", orderNo);
        String token = WePaySignatureUtil.getToken("POST", path,
                JSON.toJSONString(mchid), properties);
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);
        Call<JSONObject> call = service.wxCloseOrder(token, mchid, orderNo);
        return call.execute();
    }

    public WeixinRefundResponse wxRefunds(String orderNo, String notifyUrl, AmountEntity amount) {
        WeixinRefundRequest request = new WeixinRefundRequest(orderNo, StringUtil.getUuid(), amount);
        request.setNotify_url(notifyUrl);

        String token = WePaySignatureUtil.getToken("POST", PayUrlPath.WX_REFUNDS,
                JSON.toJSONString(request), properties);
        PayClientApi service = Network.remote(PayClientApi.class, httpObjectPoolTemplate);
        Call<WeixinRefundResponse> call = service.wxRefunds(token, request);
        return call.execute();
    }
}
